Aiven に AWS Client VPN 経由でセキュアに接続する
ウィスキー、シガー、パイプをこよなく愛する大栗です。
クライアント PC からクラウド上のデータベースに直接接続しようとするとセキュリティ面で不安になりますよね。ユーザー ID とパスワードだけの認証だとインターネットでパブリックに公開するのはためらわれるのでセキュアなネットワークを経由してデータベース(今回は Aiven を使用)に接続しようと思います。
Aiven と AWS Client VPN のネットワーク概要
以下のような概要になります。AWS Client VPN を経由するので AWS に VPC を作成して Aiven とピアリング接続を行います。また VPN の認証は相互認証とします。
今回は自分の VPC の CIDR を172.16.0.0/16
、Aiven の CIDR を10.1.0.0/20
で設定しています。
やってみた
まずは、Aiven と AWS の VPC をピアリング接続します。
以下のエントリを参考に、1. Aiven の VPC を作成する
〜4. Aiven サービスを作成する
を行います。
次に AWS の VPC に Client VPN の設定を実施します。
まずは Client VPN 用のログ出力先を作成します。
CloudWatch のロググループの画面からロググループを作成
をクリックします。
ロググループの名称を設定して作成
をクリックします。ここでは/aiven/cvpn
としました。
次にログストリームを作成します。先ほど作成したロググループのリンクをクリックします。
ログストリームを作成
をクリックします。
ログストリーム名を入力してCreate
をクリックします。ここではconnection-log
としました。
次に VPN の認証のための証明書を作成します。
ドキュメントの手順通りに相互認証のための証明書を作成します。
OpenVPN easy-rsa リポジトリをクローンします。
$ git clone https://github.com/OpenVPN/easy-rsa.git Cloning into 'easy-rsa'... remote: Enumerating objects: 2095, done. remote: Counting objects: 100% (13/13), done. remote: Compressing objects: 100% (11/11), done. remote: Total 2095 (delta 3), reused 4 (delta 0), pack-reused 2082 Receiving objects: 100% (2095/2095), 11.72 MiB | 10.37 MiB/s, done. Resolving deltas: 100% (916/916), done.
easy-rsa のディレクトリへ移動します。
$ cd easy-rsa/easyrsa3
新しい PKI 環境を初期化します。
$ ./easyrsa init-pki init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /file/to/path/easy-rsa/easyrsa3/pki
新しい認証局 (CA) を構築します。途中入力を求められますが。今回はコモンネームをデフォルト(そのまま決定)にしています。
$ ./easyrsa build-ca nopass Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017 Generating RSA private key, 2048 bit long modulus ..........................+++ ......................................+++ e is 65537 (0x10001) You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]: # CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /file/to/path/easy-rsa/easyrsa3/pki/ca.crt
サーバー証明書とキーを生成します。
$ ./easyrsa build-server-full server nopass Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017 Generating a 2048 bit RSA private key ............................+++ ..........................+++ writing new private key to '/file/to/path/easy-rsa/easyrsa3/pki/easy-rsa-1507.Tkprxk/tmp.iOdaW7' ----- Using configuration from /file/to/path/easy-rsa/easyrsa3/pki/easy-rsa-1507.Tkprxk/tmp.4Y2U0b Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'server' Certificate is to be certified until Apr 24 08:32:16 2024 GMT (825 days) Write out database with 1 new entries Data Base Updated
クライアント証明書とキーを生成します。
$ ./easyrsa build-client-full client1.domain.tld nopass Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017 Generating a 2048 bit RSA private key .............+++ ...........................................+++ writing new private key to '/file/to/path/easy-rsa/easyrsa3/pki/easy-rsa-1725.nMAe8A/tmp.b5n1Tf' ----- Using configuration from /file/to/path/easy-rsa/easyrsa3/pki/easy-rsa-1725.nMAe8A/tmp.6rVkpl Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'client1.domain.tld' Certificate is to be certified until Apr 24 08:33:34 2024 GMT (825 days) Write out database with 1 new entries Data Base Updated
証明書類を別ディレクトリにコピーします。
mkdir ~/aiven-vpn/ cp pki/ca.crt ~/aiven-vpn/ cp pki/issued/server.crt ~/aiven-vpn/ cp pki/private/server.key ~/aiven-vpn/ cp pki/issued/client1.domain.tld.crt ~/aiven-vpn cp pki/private/client1.domain.tld.key ~/aiven-vpn/ cd ~/aiven-vpn/
サーバー証明書を ACM へアップロードします。
$ aws acm import-certificate --certificate fileb://server.crt --private-key fileb://server.key --certificate-chain fileb://ca.crt { "CertificateArn": "arn:aws:acm:ap-northeast-1:123456789012:certificate/a1b2c3d4-1234-abcd-1234-1a2b3c4d5e6f" }
クライアント証明書を ACM へアップロードします。
$ aws acm import-certificate --certificate fileb://client1.domain.tld.crt --private-key fileb://client1.domain.tld.key --certificate-chain fileb://ca.crt { "CertificateArn": "arn:aws:acm:ap-northeast-1:123456789012:certificate/1a2b3c4d-abcd-1234-abcd-a1b2c3d4e5f6" }
次に Client VPN のエンドポイントを作成します。
VPC のクライアント VPN エンドポイントの画面からクライアント VPN エンドポイントの作成
をクリックします。
名前タグに任意の名称を設定します。ここではaiven-cvpn
としています。また、クライアント IPv4 CIDR では、各 VPC やローカルマシンがアクセスしない IP アドレス帯をせっています。ここでは100.64.0.0/22
を設定します(100.64.0.0/22 は ISP Shared Address ですが、もし影響がある場合は別のものに変更してください)。
サーバー証明書 ARN は、先程アップロードしたサーバー証明書の ARN を設定します。クライアント証明書 ARN は、アップロードしたクライアント証明書の ARN を設定します。
接続の詳細を確認するためクライアント接続の詳細を記録しますか?
ではい
を設定して、CloudWatch Logs ロググループ名と CloudWatch Logs ログストリーム名に作成したものを設定します。
スプリットトンネルを有効にする
をチェックして、クライアント VPN エンドポイントの作成
をクリックします。
Client VPN のエンドポイントが作成されました。
次のクライアント VPN エンドポイントをサブネットと関連付けます。
作成したクライアント VPN エンドポイントを選択して、関連付けタブを表示します。ここで関連付け
をクリックします。
エンドポイントを関連付ける VPC とサブネットを選択して、関連付け
をクリックします。
これでクライアント VPN エンドポイントがサブネットに関連付けられました。
次に認証ルールを設定します。まずは、接続している VPC を追加します。
認証タブで受信の承認
をクリックします。
アクセスを有効にする送信先ネット
に接続している VPC の CIDR(ここでは 172.16.0.0/16)を入力して認証ルールの追加
をクリックします。
認証ルールが追加されました。
次に Aiven 側の VPC の CIDR の認証ルールを追加します。先程と同様に受信の承認
クリックします。
アクセスを有効にする送信先ネット
に Aiven の VPC の CIDR(ここでは 10.1.0.0/20)を入力して認証ルールの追加
をクリックします。
認証ルールが追加されました。
クライアント VPN エンドポイントのルートテーブルも追加します。ルートテーブルタブでルートの作成
をクリックします。
ルート送信先に Aiven の VPC の CIDR を入力して、ターゲット VPC サブネット ID にクライアント VPN エンドポイントを設定しているサブネットを選択します。そしてルートの作成
をクリックします。
クライアント設定のテンプレートファイルをダウンロードします。クライアント設定のダウンロード
をクリックします。
対象のクライアント VPN エンドポイントか確認してダウンロード
をクリックします。するとdownloaded-client-config.ovpn
をダウンロードします。
downloaded-client-config.ovpn
を編集していきます。downloaded-client-config.ovpn
の末尾に``タグを追加して、中身はclient1.domain.tld.crt
の最後の証明書部分を入力します。
<cert> -----BEGIN CERTIFICATE----- ・ # client1.domain.tld.crt の内容 ・ -----END CERTIFICATE----- </cert>
さらにdownloaded-client-config.ovpn
の末尾に追加します。``タグを追加して、中身はclient1.domain.tld.key
の内容を入力して保存します。
<key> -----BEGIN PRIVATE KEY----- ・ # client1.domain.tld.key の内容 ・ -----END PRIVATE KEY----- </key>
最後にクライアント側の設定を行います。
AWS Client VPN のダウンロードページからご自身の環境にあった AWS Client VPN for Desktop をダウンロードします。Linux 版ではインストールドキュメントが表示されますので、内容に従いインストールします。
ダウンロードしたファイルを実行してインストールを進めます。
使用許諾契約も内容を確認しましょう。
インストールが終わったら AWS VPN Client を実行します。
メニューの [ファイル] > [プロファイルを管理] を選択します。
プロファイルを追加
をクリックします。
表示名を入力します。ここではAiven VPN
とします、VPN 設定ファイルに編集したdownloaded-client-config.ovpn
を指定してプロファイルを追加
をクリックします。
完了
をクリックします。
Aiven VPN
を選択して接続
をクリックします。
これで VPN 経由で Aiven にネットワークが繋がりました。
psql で接続してみます。
% psql -h pg-vpn-1-hajime-ff19.aivencloud.com -p 12492 -U avnadmin -d defaultdb Password for user avnadmin: # パスワードを入力 psql (14.1, server 13.5) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. defaultdb=> select inet_server_addr(); inet_server_addr ------------------ 10.1.5.171 (1 row)
このように VPN 経由で安全に Aiven へ接続が可能になりました。
最後に
Aiven と言いながらはネットワークに関するエントリーでした。本内容は基本的にクライアント VPN 経由で VPC Peering した先へアクセスする時に設定になっています。ポイントとしては、認証ルールとルートテーブルにピアリング先の CIDR を追加することです。
AWS の場合にセキュアに接続する手順を書いたので、次は Google Cloud 版も書いてみようかと思います。